package org.polyforms.repository.hibernate;

import javax.persistence.EntityManager;

import org.hibernate.engine.EntityEntry;
import org.hibernate.engine.ForeignKeys;
import org.hibernate.engine.SessionImplementor;
import org.polyforms.repository.spi.EntityHelper;

/**
 * Implementation of {@link EntityHelper} for Hibernate.
 * 
 * @author Kuisong Tong
 * @since 1.0
 */
public final class HibernateEntityHelper implements EntityHelper {
    private final EntityManager entityManager;

    /**
     * Create an instance with {@link EntityManager}.
     */
    public HibernateEntityHelper(final EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    /**
     * {@inheritDoc}
     */
    public boolean isEntity(final Class<?> candidate) {
        return HibernateUtil.getClassMetadata(entityManager, candidate) != null;
    }

    /**
     * {@inheritDoc}
     */
    public boolean isDetached(final Object entity) {
        final EntityEntry entry = getEntityEntry(entity);
        if (entry != null) {
            return false;
        }
        return !isTransient(entity);
    }

    private EntityEntry getEntityEntry(final Object entity) {
        return ((SessionImplementor) HibernateUtil.getSession(entityManager)).getPersistenceContext().getEntry(entity);
    }

    private boolean isTransient(final Object entity) {
        return ForeignKeys
                .isTransient(null, entity, null, (SessionImplementor) HibernateUtil.getSession(entityManager));
    }
}
